昨天筆者拋出了一個問題:我們能不能讓 ListView 的一個 Item,不只有一個 TextView,而是包含多個 Views 呢? (例如一個 ImageView 加一個 TextView)。
答案是肯定的,為了達成這目的,我們必須做兩件事:(1) 產生 Item 的 Layout 檔;(2) 自己寫一個 Adapter。首先來看 Item 的 Layout 檔,筆者在 res/layout 下產生一個名為 listitem_baby.xml 的檔案,內容如下所示:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="6dp"
android:paddingLeft="7dp"
android:paddingRight="7dp"
android:paddingTop="5dp"
android:background="#EBEBEB" >
<ImageView android:id="@+id/iv_headshot"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignParentLeft="true"
/>
<ImageView android:id="@+id/iv_gender"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_toRightOf="@id/iv_headshot"
android:paddingLeft="5dp"
/>
<TextView android:id="@+id/tv_name"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="20sp"
android:paddingLeft="5dp"
android:layout_toRightOf="@id/iv_gender"
/>
</RelativeLayout>
這個檔案應該不需特別解說了,總而言之,我們就是讓這個 Item 包含了兩個 ImageView 和一個 TextView,接下來就要自己寫一個 Adapter 了,筆者在 src/main/java/babymanager 下建立一個 BabyArrayAdapter.java,其內容如下所示:
package lincyu.babylog.babymanager;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import java.util.ArrayList;
import lincyu.babylog.R;
import lincyu.babylog.Util;
import lincyu.babylog.db.Baby;
public class BabyArrayAdapter extends ArrayAdapter<Baby> {
LayoutInflater inflater;
Drawable defaultheadshot;
public BabyArrayAdapter(Context context, ArrayList<Baby> babylist) {
super(context, 0, babylist);
inflater = LayoutInflater.from(context);
defaultheadshot = context.getResources().getDrawable(R.drawable.defaultheadshot);
}
public void fillContent(Context mContext, ViewGroup group, Baby baby){
ImageView iv_headshot = (ImageView)group.findViewById(R.id.iv_headshot);
ImageView iv_gender = (ImageView)group.findViewById(R.id.iv_gender);
TextView tv_name = (TextView)group.findViewById(R.id.tv_name);
tv_name.setText(baby.toString());
iv_headshot.setImageDrawable(defaultheadshot);
iv_gender.setImageResource(Util.getGenderPicture(baby.gender));
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
RelativeLayout itemlayout = null;
if(convertView == null) {
itemlayout = (RelativeLayout)inflater.inflate
(R.layout.listitem_baby, null);
} else {
itemlayout = (RelativeLayout) convertView;
}
fillContent(getContext(), itemlayout, getItem(position));
return itemlayout;
}
}
這個 Java 檔繼承了 ArrayAdapter<Baby>,程式 25~29 行定義了建構子,需傳入一個Context物件和一個 Baby 動態陣列,為了客製化自己的 Item,我們要覆寫 getView,44~50 行是要產生 Item 的 View 物件,首先在 27 行,我們產生一個LayoutInflater物件 [1],您可透過呼叫LayoutInfalter裡的static方法from來取得一個LayoutInflater物件,這個物件最主要的功能是把一個XML版面設計檔轉換成一個View物件,不過根據Adapter介面裡對於getView的說明 [2],我們要先判斷convertView是否是null,如果不是null,我們直接把convertView設定成我們要回傳的View,如果是null,我們才用LayoutInflater來產生要回傳的View,inflate方法需要兩個參數,第一個是「要轉換的xml檔的資源id」,第二個是要填入一個做為root的View,由於我們沒有要把這個View加到已經存在的View上面,因此填入null就可以了,由於 listitem_baby.xml 的根標籤是一個 RelativeLayout,因此在 46 行我們將 view 強制轉型成 RelativeLayout。
接著程式在 51 行呼叫 getItem 取出對應的 Baby 物件,然後在 33 ~ 35 行呼叫 findViewById 找出 RelativeLayout下的 TextView與ImageView,並將Baby 的相關資料設給TextView與ImageView。
現在回到 BabyListActivity.java,將 ArrayAdapter 改成 BabyArrayAdapter 如下所示:
// private ArrayAdapter<Baby> adapter;
private BabyArrayAdapter adapter;
// adapter = new ArrayAdapter(BabyListActivity.this,
// R.layout.listitem,
// R.id.tv_listitem,
// babylist);
adapter = new BabyArrayAdapter(BabyListActivity.this, babylist);
執行結果則如下圖所示:
更多客製化 ListView 的範例與說明可參考筆者的書籍 [3]。
參考資料
[1] LayoutInflater | Android Developers, http://developer.android.com/reference/android/view/LayoutInflater.html
[2] Adapter | Android Developers, http://developer.android.com/reference/android/widget/Adapter.html
[3] 林致宇, Android程式設計入門與應用(附範例光碟), 全華出版社, ISBN: 9789572194126, http://www.opentech.com.tw/search/bookinfo.asp?isbn=9789572194126&companyID=04383129